package com.shockweb.service.ioc.impl;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.springframework.aop.support.AopUtils;
import com.shockweb.common.utils.classmethod.ClassMethod;
import com.shockweb.bridge.ServiceRequest;
import com.shockweb.service.ServiceServerException;
import com.shockweb.service.ioc.IocInvoke;
import com.shockweb.service.ioc.impl.spring.SpringContextUtils;

import javassist.NotFoundException;

/**
 * spring web的IOC容器，负责执行微服务
 * 
 * @author 彭明华
 * 2018年1月19日 创建
 */
public class SpringWebIocInvokeImpl implements IocInvoke{

	
	
	/**
	 * 执行Spring服务
	 */
	public Object invoke(String serviceName, ServiceRequest req) throws ServiceServerException {
		try{
			Object instance = SpringContextUtils.getApplicationContext().getBean(serviceName);
			if(instance!=null){
				Object result = null;
				Class<?> clazz = null;
				if(AopUtils.isCglibProxy(instance)){
					clazz = instance.getClass().getSuperclass();
				}else{
					clazz = instance.getClass();
				}
				Method method = ClassMethod.getMethod(clazz, req.getMethod(),req.getParameterTypes());
				if(method!=null){
					if(req.getParameterTypes()==null){
						result = method.invoke(instance);
					}else{
						result = method.invoke(instance, req.getParams());
					}
				}else{
					throw new ServiceServerException("找不到 serviceName '" + serviceName + "'类中'" + req.getMethod() + "'方法");
				}
				return result;
			}
			return null;
		}catch(ServiceServerException e){
			throw e;
		}catch(InvocationTargetException e){
			throw new ServiceServerException("执行 serviceName '" + serviceName + "'服务出错",e.getTargetException());
		}catch(IllegalAccessException | IllegalArgumentException
				| SecurityException | NotFoundException | NoSuchMethodException | ClassNotFoundException e){
			throw new ServiceServerException("执行 serviceName '" + serviceName + "'服务出错",e);
		}
	}

	/**
	 * 判断服务是否可执行
	 */
	public boolean ableInvoke(String serviceName) {
		try{
			Object instance = SpringContextUtils.getApplicationContext().getBean(serviceName);
			if(instance!=null){
				return true;
			}else{
				return false;
			}
		}catch(Throwable e){
			return false;
		}
	}

}
